package com.whz.mlc.provider.loader;

import com.google.common.collect.Maps;
import com.whz.generic.utils.SafeExecutor;
import com.whz.mlc.exception.BeanNotFoundException;
import com.whz.mlc.provider.MlcCacheDefinition;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Map;

/**
 * @author whz
 * 2021/8/26
 */
public class MlcCompositeCacheLoader implements MlcCacheLoaderProvider, ApplicationContextAware, DisposableBean {

    private final Map<String, MlcCacheDefinition> loaders = Maps.newHashMap();
    private ApplicationContext applicationContext;

    public MlcCompositeCacheLoader(Collection<MlcCacheDefinition> tmcSecondCacheLoaders) {
        addLoaders(tmcSecondCacheLoaders);
    }

    public void addLoaders(Collection<MlcCacheDefinition> tmcSecondCacheLoaders) {
        SafeExecutor.consumerList(tmcSecondCacheLoaders, loader -> loaders.putIfAbsent(loader.cacheName(), loader));
    }

    @Override
    public MlcCacheDefinition getMlcCacheDefinition(final String cacheName) {
        if (!loaders.containsKey(cacheName)) {
            initLoaders();
        }
        MlcCacheDefinition tmcCacheLoaders = loaders.get(cacheName);
        if (tmcCacheLoaders == null) {
            throw new BeanNotFoundException("未找到cacheName:'" + cacheName + "'的MlcCacheDefinition.");
        }
        // 优先级最高的
        return tmcCacheLoaders;
    }

    private void initLoaders() {
        Map<String, MlcCacheDefinition> beans = applicationContext.getBeansOfType(MlcCacheDefinition.class);
        if (!CollectionUtils.isEmpty(beans)) {
            addLoaders(beans.values());
        }
    }

    @Override
    public void setApplicationContext(@NonNull final ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void destroy() {
        loaders.clear();
    }
}